

                     L                ZZZZZZ         RRRRR           SSSSS
                     L                    Z          R    R         S
                     L          aaa      Z      aaa  R    R  u   u  S
                     L            a     Z         a  RRRRR   u   u  SSSSS
               XX    L         aaaa    Z       aaaa  R    R  u   u       S
              XXXX   L        a   a   Z       a   a  R    R  u   u       S
             XXXXXX  LLLLLLL  aaaaa  ZZZZZZZ  aaaaa  R    R  uuuuu  SSSSSS
             XXXXXX       
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
             XXXXXX
             XXXXXX
              XXXX        proudly presents his 19.Cracking Tutorial (04.07.1999)
               XX                   	Cruehead's CrackMe 1.0

I.    Introduction
I.1   Tools you need for my tutorial
II.   The "Kick the nag" approach
VI.   BTW
VII.  All Tutorials by LaZaRuS

I.   Welcome to my 20st cracking tutorial.

I.1  W32Dasm 8.9
     Cruehead's CrackMe 1.0
 
II.  Thanx Cruehead. I thought first that this one will be pretty easy and could be done in one
     minute. But I fastly saw that I would have to follow the serial calculation. So I needed
     two minutes ;)

     Whatever, let's start. (Although there's no need to disassemble it (as you say), I only have
     W32Dasm on this computer and my SICE is 900km away from here :( So I have to break this 
     rule). Load CrackMe.exe in W32Dasm. You will see some string references. The most important
     is "Great work, mate!". Search for it and you see this:

     * Referenced by a CALL at Address:
     |:0040124C   
     |
     :0040134D 6A30                    push 00000030

     * Possible StringData Ref from Data Obj ->"Good work!"
                                       |
     :0040134F 6829214000              push 00402129

     * Possible StringData Ref from Data Obj ->"Great work, mate!"
                                       |
     :00401354 6834214000              push 00402134
     :00401359 FF7508                  push [ebp+08]

     * Reference To: USER32.MessageBoxA, Ord:0000h
                                  |
     :0040135C E8D9000000              Call 0040143A
     :00401361 C3                      ret

     We can easily see that this messagebox is called from :0040124C. So let's have a look at
     this passage.

     :00401240 58                      pop eax       ;; load one value
     :00401241 3BC3                    cmp eax, ebx  ;; compare two values
     :00401243 7407                    je 0040124C   ;; if same, then jump to "Well done" message
     :00401245 E818010000              call 00401362 ;; call "wrong" message
     :0040124A EB9A                    jmp 004011E6  ;; go on

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:00401243(C)
     |
     :0040124C E8FC000000              call 0040134D  ;; call "well done" messagebox
     :00401251 EB93                    jmp 004011E6   ;; go on

     So pretty obviously: Either eax or ebx should contain the correct serial and the other 
     register should contain the value you have entered, then. When you try it you will see that
     is not this way. So we have to follow how these two values are calculated.

     :00401228 688E214000              push 0040218E ;; 40218E contains the name you entered
     :0040122D E84C010000              call 0040137E ;; calculates first value
     :00401232 50                      push eax      ;; saves first value
     :00401233 687E214000              push 0040217E ;; saves serial you entered
     :00401238 E89B010000              call 004013D8 ;; calculates second value
     :0040123D 83C404                  add esp, 00000004
     :00401240 58                      pop eax       ;; loads first value
     :00401241 3BC3                    cmp eax, ebx  ;; compare first with second value
     :00401243 7407                    je 0040124C   ;; if same, then jump to "Well done"

     The first call is this:

     * Referenced by a CALL at Address:
     |:0040122D   
     |
     :0040137E 8B742404                mov esi, dword ptr [esp+04]  ;; esi=name
     :00401382 56                      push esi                     ;; save name

     * Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
     |:00401392(U), :0040139A(U)
     |
     :00401383 8A06                    mov al, byte ptr [esi]       ;; mov first letter in al
     :00401385 84C0                    test al, al                  ;; al=0 ?
     :00401387 7413                    je 0040139C                  ;; if so, then exit loop
     :00401389 3C41                    cmp al, 41                   ;; al<41? (41h=65=A)
     :0040138B 721F                    jb 004013AC                  ;; if so, then "Wrong"
     :0040138D 3C5A                    cmp al, 5A                   ;; if al >= 5A (5A=90=Z)
     :0040138F 7303                    jnb 00401394                 ;; if so, then jump
     :00401391 46                      inc esi                      ;; point to next letter
     :00401392 EBEF                    jmp 00401383                 ;; loop

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:0040138F(C)
     |
     :00401394 E839000000              call 004013D2                ;; ASCII(letter) - 20h
     :00401399 46                      inc esi                      ;; point to next letter
     :0040139A EBE7                    jmp 00401383                 ;; loop

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:00401387(C)
     |
     :0040139C 5E                      pop esi                      ;; load name again
     :0040139D E820000000              call 004013C2                ;; see below
     :004013A2 81F778560000            xor edi, 00005678            ;; XOR value with 5678h
     :004013A8 8BC7                    mov eax, edi                 ;; save value in eax
     :004013AA EB15                    jmp 004013C1                 ;; go on

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:0040138B(C)
     |
     :004013AC 5E                      pop esi                      ;; show a "Wrong" MessageBox
     :004013AD 6A30                    push 00000030 
  
     * Possible StringData Ref from Data Obj ->"No luck!"
                                       |
     :004013AF 6860214000              push 00402160

     * Possible StringData Ref from Data Obj ->"No luck there, mate!"
                                       |
     :004013B4 6869214000              push 00402169
     :004013B9 FF7508                  push [ebp+08]

     * Reference To: USER32.MessageBoxA, Ord:0000h
                                       |
     :004013BC E879000000              Call 0040143A

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004013AA(U)
     |
     :004013C1 C3                      ret

     Let's explain: This passage does nothing but converting the name you entered to capital
     letters. LaZaRuS will be LAZARUS after this passage. Eh, not really. I assume Cruehead
     made a mistake coding this passage. LaZaRuS will be LA:ARUS after this passage. In my 
     opinion the following line:

     :0040138F 7303                    jnb 00401394                 ;; if so, then jump

     must be

     :0040138F 7?03                    jb 00401394                  ;; if so, then jump

     Then the name would be converted correctly. I'll ask Cruehead when I meet him next time.

     So let's have a look at the call :0040139D

     * Referenced by a CALL at Address:
     |:0040139D   
     |
     :004013C2 33FF                    xor edi, edi  ;; erase edi
     :004013C4 33DB                    xor ebx, ebx  ;; erase ebx

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004013CF(U)
     |
     :004013C6 8A1E                    mov bl, byte ptr [esi]  ;; bl = 1st char of conv. name
     :004013C8 84DB                    test bl, bl             ;; bl=0?
     :004013CA 7405                    je 004013D1             ;; if so, then exit loop
     :004013CC 03FB                    add edi, ebx            ;; edi=edi + 1st letter
     :004013CE 46                      inc esi                 ;; point to next letter
     :004013CF EBF5                    jmp 004013C6            ;; loop

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004013CA(C)
     |
     :004013D1 C3                      ret                     ;; return from call

     This passage will add all ASCII values of each letter of the converted string. For LA:ARUS
     this will be: 4C+41+3A+41+52+55+53 (hex values). This is 202h. When you return from the call
     this value will be XORed with 5678h. The result is 547Ah. This is one of the values that
     are compared at the end. So, let's look for the other.
     The important call is at :00401238. If you enter, you will see this:

     * Referenced by a CALL at Address:
     |:00401238   
     |
     :004013D8 33C0                    xor eax, eax  ;; erase eax
     :004013DA 33FF                    xor edi, edi  ;; erase edi
     :004013DC 33DB                    xor ebx, ebx  ;; erase ebx
     :004013DE 8B742404                mov esi, dword ptr [esp+04]  ;; esi=serial

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004013F3(U)
     |
     :004013E2 B00A                    mov al, 0A             ;;-------------- This one just
     :004013E4 8A1E                    mov bl, byte ptr [esi] ;;             | copies the serial
     :004013E6 84DB                    test bl, bl            ;;             | you entered to edi
     :004013E8 740B                    je 004013F5            ;;             | I entered 666999
     :004013EA 80EB30                  sub bl, 30             ;;             | so edi will 
     :004013ED 0FAFF8                  imul edi, eax          ;;             | contain A2D77 (the
     :004013F0 03FB                    add edi, ebx           ;;             | hex-value of my
     :004013F2 46                      inc esi                ;;             | serial) at the end
     :004013F3 EBED                    jmp 004013E2           ;;--------------

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004013E8(C)
     |
     :004013F5 81F734120000            xor edi, 00001234      ;; XORes the serial with 1234h
     :004013FB 8BDF                    mov ebx, edi           ;; saves second value in ebx
     :004013FD C3                      ret                    ;; return from call

     The value I get is A3F43h (A2D77h XOR 1234h). That's obviously not the same as 547Ah which
     I got as first value. The first value is unchangable (as I want to reg it with LaZaRuS), so
     let's have a look at the second one.

     We know:
     [All letters of name added] XOR 5678h == Serial XOR 1234h
                                     547Ah == Serial XOR 1234h
     -> serial = 547Ah XOR 1234h
        serial = 464E

     We have to convert this value back to decimal: 17998

     So at the end we have:
     Name: LaZaRuS
     Code: 17998


I.  BTW
     
     Greets to: tKC, Ed!son, Moral Insanity, +Sandman, Fravia+ and everyone at #cracking4newbies,
     +Sandman's forum and Fravia+'s forum.

VII. All tutorials by LaZaRuS
      
